home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / vol_100 / 108_01 / kwic.c < prev    next >
Text File  |  1985-11-13  |  7KB  |  229 lines

  1.  
  2. /**********************************************************
  3.  ***                            ***
  4.  ***    Copyright (c) 1981 by David M. Fogg        ***
  5.  ***                            ***
  6.  ***        2632 N.E. Fremont            ***
  7.  ***        Portland, OR 97212            ***
  8.  ***                            ***
  9.  ***        (503) 288-3502{HM} || 223-8033{WK}        ***
  10.  ***                            ***
  11.  ***    Permission is herewith granted for non-     ***
  12.  ***    commercial distribution through the BDS C    ***
  13.  ***    User's Group; any and all forms of commercial   ***
  14.  ***    redistribution are strenuously unwished-for.    ***
  15.  ***                            ***
  16.  **********************************************************/
  17.  
  18. /* --->  K W I C  <--- : generate KeyWordInContext raw outfile
  19.  
  20.     29 OCT 80: convert from WC -> BDS
  21.     30 Oct: add chain code
  22.     31 Oct: reverse -C option function
  23.     5 Nov: add -N -O options
  24.     29 Jan 81: add -L option
  25.  
  26.     Programs generates rotated lines from IFILE to IFILE.UNK
  27.       for sorting to generate a KWIC Index.
  28.  
  29.     Words in skip list or == 1 char long are skipped;
  30.       skip list is originally: AN, THE, AND, OR.
  31.  
  32.     Although chars are output in the same case they are input,
  33.       they are internally converted to uppercase for skip list test.
  34.  
  35.     -A option: if on, defines word begin as 1st ALPHANUMERIC char,
  36.       rather than first non-whitespace (NB: this affects word length).
  37.     -C option: defeats auto-chain -> MSORT -> MERGE.
  38.     NB: auto-chain turns on Ignore case option in MSORT & MERGE.
  39.          MSORT will kill IFILE.UNK; MERGE will kill IFILE.A+...
  40.          KWIC calculates and passes on average line length to
  41.         MSORT for most efficient use of sort buffer.
  42.     -Ln option: set Line Length to 'n' in arg list to MSORT
  43.          (default: 40)
  44.     -Nc option: char 'c' at the beginning of a word causes that word to
  45.     be skipped (NB: -A option turned off).
  46.     -Oc option: char 'c' MUST be at the beginning of a word for that
  47.     word to be used (NB: overrides -A & -N options).
  48.  
  49.     Additional arguments in input command line are taken as
  50.       words to add to the skip list.
  51.  
  52.     If no ODRIV is specified, all files will be created on the input
  53.     file drive; if ODRIV is specified, then the files will ping-pong
  54.     between input file drive & ODRIVE. For example:
  55.  
  56.         KWIC INDEX.RAW B:           (A:INDEX.RAW --> B:INDEX.UNK)
  57.         MSORT B:INDEX.UNK -I -L40     (B:INDEX.UNK --> A:INDEX.A+...)
  58.         MERGE INDEX B:INDEX.KWC -I    (A:INDEX.A+... --> B:INDEX.KWC)
  59.  
  60. */
  61.  
  62. #include <std.h>
  63.  
  64. #define MAXLEN    130     /* max line length */
  65. #define MSKIPS    30      /* max # of words in skiplist */
  66. #define DEFLEN    40      /* default line length */
  67.  
  68. main (ac, av)
  69. int ac;
  70. char *av[];
  71. {
  72.     char ilin[MAXLEN];      /* input line buffer */
  73.     char tlin[MAXLEN];      /* test line buffer {UCASE ilin} */
  74.     int llen;             /* length of current line */
  75.     int curwd;            /* pos of 1st char of curr wd */
  76.     int wdlen;            /* length of curr wd */
  77.     int i;
  78.     BOOL alfon;         /* whether to start words @ 1st alfanum */
  79.     BOOL only;            /* ONLY-words-starting-w/a-char flag */
  80.     BOOL not;             /* NOT  ditto above */
  81.     char onlych;        /* ONLY start char allowed */
  82.     char notch;         /* NOT allowed 2b start char */
  83.     int nxarg;
  84.     char ibuf[BUFSIZ];      /* infile buffer */
  85.     char obuf[BUFSIZ];      /* outfile buffer */
  86.     int nskips;         /* # of words in default skip list */
  87.     char *skips[MSKIPS]; /* pointers to skip list words */
  88.     BOOL gosort;        /* to chain or not to chain */
  89.     char inam[15];       /* input file name */
  90.     char onam[15];       /* output file name */
  91.     int ppos;             /* period position in onam */
  92.     int argn;             /* curr arg# in options code */
  93.     char *arg;            /* curr arg in options code */
  94.     char avlen[20];       /* str vrsn of avg line len of ofile */
  95.  
  96. /*
  97.       ---> INITIALIZATION <---
  98. */
  99.     gosort = YES; alfon = only = not = NO;
  100.     notch = onlych = NULL;
  101.     nskips = 4;
  102.     nxarg = 2;
  103.     strcpy(avlen, "-L40");
  104.  
  105.     skips[0] ="AN"; skips[1] ="THE"; skips[2] ="AND"; skips[3] ="OR";
  106.  
  107.     if (ac < 2) {
  108.     puts("usage: kwic IFILE [ODRIV] [-A -C -Ln -Nc -Oc] [words]\n");
  109.     puts("IFILE: name of input file\n");
  110.     puts("ODRIV: (e.g., B:) where to put IFILE.UNK\n");
  111.     puts("   -A: start words @ 1st ALFANUMERIC, 'stead of 1st non-blank\n");    puts("   -C: don't CHAIN to msort & merge\n");
  112.     puts("  -Ln: avg. line length arg for msort (default: 40)\n");
  113.     puts("  -Nc: NOT use words that start with <c>\n");
  114.     puts("  -Oc: ONLY use words that start with <c>\n");
  115.     puts("words: added to skip list (an the and or)\n");
  116.     exit ();
  117.     }
  118.  
  119.     strcpy(inam, av[1]);
  120.     if (fopen(inam, ibuf) == ERROR)
  121.     errxit("Input file error");
  122.  
  123.     if (ac > 2 && *(av[2]+1) == ':') {        /* set up outfile name */
  124.     strcpy(onam, av[2]);
  125.     if (strlen(onam) > 2) errxit("Bad output drive field");
  126.     strcat(onam, inam + instr(inam, ":"));
  127.     ++nxarg;
  128.     }
  129.     else
  130.     strcpy(onam, inam);
  131.     if (ppos = instr(onam, "."))
  132.     strcpy(onam + ppos, "UNK");
  133.     else
  134.     strcat(onam, ".UNK");
  135.  
  136.     if (fcreat(onam, obuf) == ERROR)
  137.     errxit("Output file error");
  138.  
  139.  
  140.     /*
  141.     ---> GET OPTIONS <---
  142.     */
  143.     for (argn = 1; argn < ac; ++argn) {
  144.     arg = av[argn];
  145.     if (*arg == '-')
  146.         switch (arg[1]) {
  147.         case 'C':
  148.             gosort = NO; ++nxarg;
  149.             break;
  150.         case 'A':
  151.             alfon = YES; ++nxarg;
  152.             break;
  153.         case 'L':
  154.             strcpy(avlen, arg);
  155.             break;
  156.         case 'N':
  157.             not = YES; notch = arg[2]; ++nxarg;
  158.             alfon = only = NO; onlych = NULL;
  159.             break;
  160.         case 'O':
  161.             only = YES; onlych = arg[2]; ++nxarg;
  162.             alfon = not = NO; notch = NULL;
  163.             break;
  164.         default :
  165.             errxit("Bad option value");
  166.         }
  167.     }
  168.  
  169.     while (nxarg < ac)               /* get xtra skip wds (if any) */
  170.     skips[nskips++] = av[nxarg++];
  171.  
  172. /*
  173.       ---> MAIN LOOP <---
  174. */
  175.     while (fgets(ilin, ibuf) != 0) {
  176.     llen = strlen(ilin); ilin[--llen] = '\0';
  177.     for (i = 0; i < llen; ++i)
  178.         tlin[i] = toupper(ilin[i]);
  179.     tlin[llen] = NULL;
  180.     curwd = 0;
  181.     while (curwd < llen) {
  182.         while (isspace(tlin[curwd]) && ++curwd < llen)
  183.         ;
  184.         while (alfon
  185.         && !isalpha(tlin[curwd]) && !isdigit(tlin[curwd])
  186.         && ++curwd < llen)
  187.         ;
  188.         wdlen = 1;
  189.         while (!isspace(tlin[curwd+wdlen]) && curwd + wdlen < llen)
  190.         ++wdlen;
  191.         if ((only && ilin[curwd] == onlych)
  192.         || (!only && wdlen > 1
  193.           && noskip(tlin+curwd, wdlen, skips, nskips)
  194.           && (!not || ilin[curwd] != notch))) {
  195.         fprintf(obuf, "%s // ", ilin + curwd + only);
  196.         for (i = 1; i < curwd;    ++i)
  197.             putc(ilin[i-1], obuf);
  198.         fputs("\n", obuf);
  199.         }
  200.         curwd += ++wdlen;
  201.     } /* while (curwd... */
  202.     } /* while (fgets... */
  203.     fclose(ibuf); oclose(obuf);
  204.  
  205.     if (gosort) {                   /* ---> msort? */
  206.     inam[instr(inam, ":")] = NULL;
  207.     printf("\n--> msort %s %s -I %s\n", onam, inam, avlen);
  208.     execl("msort", onam, inam, "-I", avlen, 0);
  209.     }
  210. }
  211.  
  212.  
  213. BOOL noskip (wd, len, skips, nskips)     /* see if wd in skips */
  214. char *wd;
  215. int len;
  216. char *skips[];
  217. int nskips;
  218. {
  219.     int i;
  220.     char twd[MAXLEN];
  221.  
  222.     strcpy(twd, wd); twd[len] = '\0';
  223.  
  224.     for (i = 0; i < nskips; ++i)
  225.     if (strcmp(skips[i], twd) == 0)
  226.         return(NO);
  227.     return(YES);
  228. }
  229.